package com.njtoyo.taxi.admin.logic.business;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.njtoyo.taxi.admin.mapper.master.entity.*;
import com.njtoyo.taxi.admin.mapper.master.enums.*;
import com.njtoyo.taxi.admin.mapper.master.mapper.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;

@Service
@Slf4j
public class CustomerLogic {
    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private CouponMapper couponMapper;

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private RechargeMapper rechargeMapper;

    @Autowired
    private MemberPointLogMapper memberPointLogMapper;

    @Autowired
    private MemberPushTokenMapper memberPushTokenMapper;

    @Autowired
    private ActivityPointSignLogMapper activityPointSignLogMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private CustomerLogoutLogMapper customerLogoutLogMapper;

    @Transactional
    public void handleLogout(CustomerLogoutLog logout) {
        // 账户表
        Account account = accountMapper.selectOne(new QueryWrapper<Account>().eq("customer_id", logout.getCustomerId()));
        log.info("账户余额信息 {}", account);
        // 充值流水表
        if (account.getDonationAmount().compareTo(BigDecimal.ZERO) > 0) {
            // 增加扣款记录
            Recharge recharge = new Recharge();
            recharge.setOutTradeNo(DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN))
                    .setAmount(account.getDonationAmount()).setPayAmount(BigDecimal.ZERO).setCustomerId(logout.getCustomerId())
                    .setPayMethod(RechargePayMethod.cash).setState(RechargeState.done).setOperationMode(false)
                    .setPayMode(RechargePayMode.logout).setDonationAmount(account.getDonationAmount());
            log.info("新增扣款记录 {}", recharge);
            rechargeMapper.insert(recharge);
        }
        // 账户余额清零
        new LambdaUpdateChainWrapper<>(accountMapper)
                .eq(Account::getCustomerId, logout.getCustomerId())
                .set(Account::getDonationAmount, 0)
                .set(Account::getAmount, account.getPayAmount())
                .update();
        log.info("账户余额清零成功");

        // 优惠券
        String couponExpireTime = DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN);
        QueryWrapper<Coupon> couponQuery = new QueryWrapper<Coupon>()
                .eq("user_id", logout.getCustomerId())
                .eq("had_used", 0)
                .ge("ended_at", couponExpireTime);
        List<Coupon> couponList = couponMapper.selectList(couponQuery);
        log.info("未过期且未使用的优惠券信息: {}", couponList);
        // 清除优惠券
        new LambdaUpdateChainWrapper<>(couponMapper)
                .eq(Coupon::getUserId, logout.getCustomerId())
                .gt(Coupon::getEndedAt, couponExpireTime)
                .eq(Coupon::getHadUsed, 0)
                .set(Coupon::getEndedAt, couponExpireTime)
                .update();
        log.info("优惠券设置过期成功");

        // 会员信息
        Member member = memberMapper.selectOne(new QueryWrapper<Member>().eq("ref_id", logout.getCustomerId()).eq("category", MemberCategory.customer));
        log.info("会员信息 {}", member);
        if (Objects.nonNull(member)) {
            if (member.getValidPoint() > 0) {
                // 新增积分扣除记录
                MemberPointLog pointLog = new MemberPointLog();
                pointLog.setMemberId(member.getId()).setPointLogEvent(MemberPointLogEvent.customer_logout)
                        .setPoint(member.getValidPoint()).setInOut(MemberPointLogInOut.out).setRefId(member.getId())
                        .setRefType(MemberPointLogRefType.customer_logout);
                memberPointLogMapper.insert(pointLog);
                log.info("新增积分扣除记录 {}", pointLog);
            }
            // 清除账号积分，设置封号
            new LambdaUpdateChainWrapper<>(memberMapper)
                    .eq(Member::getId, member.getId())
                    .set(Member::getPoint, 0)
                    .set(Member::getValidPoint, 0)
                    .set(Member::getState, MemberState.freeze_up)
                    .update();
            log.info("清除账号会员积分数据，设置封号");
        }
        // 修改 user 表
        new LambdaUpdateChainWrapper<>(userMapper)
                .eq(User::getId, logout.getCustomerId())
                .set(User::getIsFreezed, 1)
                .set(User::getRefreshToken, null)
                .update();
        log.info("修改user表信息");
        // 清除 member_push_token 的 token数据
        memberPushTokenMapper.delete(new QueryWrapper<MemberPushToken>().eq("customer_id", logout.getCustomerId()));
        log.info("清除 member_push_token 数据");
        // customer_logout_log 修改
        new LambdaUpdateChainWrapper<>(customerLogoutLogMapper)
                .eq(CustomerLogoutLog::getId, logout.getId())
                .set(CustomerLogoutLog::getLogoutState, CustomerLogoutLogState.adopt)
                .set(CustomerLogoutLog::getAdoptTimestamp, System.currentTimeMillis() / 1000)
                .update();
        log.info("修改注销申请状态");

        // activity_point_sign_log 签到修改
        new LambdaUpdateChainWrapper<>(activityPointSignLogMapper)
                .eq(ActivityPointSignLog::getCustomerId, logout.getCustomerId())
                .ge(ActivityPointSignLog::getSignDate, DateUtil.formatDate(DateUtil.offsetDay(new Date(), -7)))
                .set(ActivityPointSignLog::getRoundFinished, true)
                .update();
        log.info("修改签到记录成功");
    }

    public List<User> selectNamePhoneByIds(Set<Long> ids) {
        return new LambdaQueryChainWrapper<>(userMapper)
                .in(User::getId, ids)
                .list();
    }
}
